//
// Created by lz on 2021/2/3.
//

#ifndef MYWEBLIB_TIMESTAMP_H
#define MYWEBLIB_TIMESTAMP_H

#include "Types.h"
#include "base/copyable.h"
#include "base/Types.h"

#include <boost/operators.hpp>

//equality_comparable：要求提供==，可自动实现!=，相等语义；
//
//less_than_comparable：要求提供<，可自动实现>、<=、>=；

namespace lzweb
{
	// timestamp -> 时间戳， unix时间戳是从1970年1月1日（UTC/GMT的午夜）开始所经过的秒数，不考虑闰秒。
class TimeStamp: public lzweb::copyable,
				 public boost::equality_comparable<TimeStamp>,
				 public boost::less_than_comparable<TimeStamp>
{
public:
	TimeStamp()
		: microSecondsSinceEpoch_(0)
	{}

	explicit TimeStamp(int64_t microSecondsSinceEpochArg)
		: microSecondsSinceEpoch_(microSecondsSinceEpochArg)
	{}

	void swap(TimeStamp &that)
	{
		std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
	}

	string toString() const;

	string toFormattedString(bool showMicroSeconds = true) const;

	bool valid() const
	{ return microSecondsSinceEpoch_ > 0; }

	int64_t microSecondsSinceEpoch() const
	{ return microSecondsSinceEpoch_; }
	//time_t == long int
	time_t secondsSinceEpoch() const
	{
		return static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);
	}

	static TimeStamp now();
	static TimeStamp invalid()
	{
		return TimeStamp();
	}

	static TimeStamp fromUnixTime(time_t t)
	{
		return fromUnixTime(t, 0);
	}

	static TimeStamp fromUnixTime(time_t t, int microseconds)
	{
		return TimeStamp(static_cast<int64_t>(t) * kMicroSecondsPerSecond + microseconds);
	}

	static const int kMicroSecondsPerSecond = 1000 * 1000;
private:
	int64_t microSecondsSinceEpoch_;
};

inline bool operator<(TimeStamp lhs, TimeStamp rhs)
{
	return lhs.microSecondsSinceEpoch() < rhs.microSecondsSinceEpoch();
}

inline bool operator==(TimeStamp lhs, TimeStamp rhs)
{
	return lhs.microSecondsSinceEpoch() == rhs.microSecondsSinceEpoch();
}

///
/// Gets time difference of two timestamps, result in seconds.
///
/// @param high, low
/// @return (high-low) in seconds
/// @c double has 52-bit precision, enough for one-microsecond
/// resolution for next 100 years.
inline double timeDifference(TimeStamp high, TimeStamp low)
{
	int64_t diff = high.microSecondsSinceEpoch() - low.microSecondsSinceEpoch();
	return static_cast<double>(diff) / TimeStamp::kMicroSecondsPerSecond;
}

///
/// Add @c seconds to given timestamp.
///
/// @return timestamp+seconds as Timestamp
///
inline TimeStamp addTime(TimeStamp timestamp, double seconds)
{
	int64_t delta = static_cast<int64_t>(seconds * TimeStamp::kMicroSecondsPerSecond);
	return TimeStamp(timestamp.microSecondsSinceEpoch() + delta);
}

}


#endif //MYWEBLIB_TIMESTAMP_H
